package igor.lakienko.ru.generation.quotes.service;

import igor.lakienko.ru.generation.quotes.dto.MessageEventDto;
import igor.lakienko.ru.generation.quotes.dto.PreciousMetalDto;
import igor.lakienko.ru.generation.quotes.entity.PreciousMetalEntity;
import igor.lakienko.ru.generation.quotes.enums.PreciousMetal;
import igor.lakienko.ru.generation.quotes.enums.RecommendationAnalysts;
import igor.lakienko.ru.generation.quotes.mapper.PreciousMetalMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.ThreadLocalRandom;

/**
 * Сервис для работы с металлами.
 */
@Service
@RequiredArgsConstructor
public class PreciousMetalService {

    private final PreciousMetalMapper preciousMetalMapper;

    @Value("${quote.responseSleepInMillis}")
    long responseSleepInMillis;

    @Value("${quote.quoteSizeBatch}")
    long metalSizeBatch;

    /**
     * Постоянное получение металлов с задержкой указанной в параметрах.
     */
    public MessageEventDto getMetal() {
        try {
            Thread.sleep(responseSleepInMillis);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        PreciousMetalEntity randomMetal = getRandomMetal();
        return preciousMetalMapper.preciousMetalEntityToDto(randomMetal);
    }

    /**
     * Получения списка металлов в размере указанном в конфигурационном файле.
     */
    public Collection<PreciousMetalDto> getMetals() {
        ArrayList<PreciousMetalEntity> metalsEntity = new ArrayList<>();
        for (int i = 0; i < metalSizeBatch; i++) {
            PreciousMetalEntity randomMetal = getRandomMetal();
            metalsEntity.add(randomMetal);
        }
        return preciousMetalMapper.preciousMetalsEntityToDto(metalsEntity);
    }

    /**
     * Получения случайного металла из списка, со случайными параметрами.
     */
    private PreciousMetalEntity getRandomMetal() {
        PreciousMetal[] metals = PreciousMetal.values();
        int randomMetal = ThreadLocalRandom.current().nextInt(metals.length);
        PreciousMetal metal = metals[randomMetal];
        float price = metal.getPrice();
        int bidVolume = ThreadLocalRandom.current().nextInt(1, 10_000);
        int offerVolume = ThreadLocalRandom.current().nextInt(1, 100_000);
        float monthlyVolatility = BigDecimal.valueOf(ThreadLocalRandom.current().nextDouble(-15.0F, 15.0F))
                .setScale(2, RoundingMode.HALF_DOWN).floatValue();

        return PreciousMetalEntity.builder()
                .preciousMetal(metal)
                .fullMetalName(metal.getDescription())
                .bidVolume(bidVolume)
                .offerVolume(offerVolume)
                .price(price)
                .recommendationAnalysts(getRecommendationAnalysts())
                .monthlyVolatility(monthlyVolatility)
                .build();
    }

    private String getRecommendationAnalysts() {
        RecommendationAnalysts[] recommendationAnalysts = RecommendationAnalysts.values();
        int randomStocks = ThreadLocalRandom.current().nextInt(recommendationAnalysts.length);
        RecommendationAnalysts recommendation = recommendationAnalysts[randomStocks];
        return recommendation.getRecommendation();
    }

}
